﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Text.RegularExpressions;
using System.Collections.Specialized;
using System.Globalization;
using System.Web.UI.WebControls;

namespace DusonFramework.Core
{
    public class HtmlHelper
    {
        /// <summary>
        /// 将字符转化为HTML编码
        /// </summary>
        /// <param name="Input">输入字符串</param>
        /// <returns>返回编译后的字符串</returns>
        public static string HtmlEncode(string Input)
        {
            return HttpContext.Current.Server.HtmlEncode(Input);
        }

        /// <summary>
        /// 将字符HTML解码
        /// </summary>
        /// <param name="Input">输入字符串</param>
        /// <returns>返回解码后的字符串</returns>
        public static string HtmlDecode(string Input)
        {
            if (string.IsNullOrEmpty(Input)) return string.Empty;
            else
                return HttpContext.Current.Server.HtmlDecode(Input);
        }

        /// <summary>
        /// 恢复html中的特殊字符
        /// </summary>
        /// <param name="theString">需要恢复的文本。</param>
        /// <returns>恢复好的文本。</returns>
        public static string HtmlDecodeWithReplace(string theString)
        {
            theString = theString.Replace("&gt;", ">");
            theString = theString.Replace("&lt;", "<");
            theString = theString.Replace("&nbsp;", " ");
            theString = theString.Replace(" &nbsp;", "  ");
            theString = theString.Replace("&quot;", "\"");
            theString = theString.Replace("&#39;", "\'");
            theString = theString.Replace("<br/> ", "\n");
            return theString;
        }

        /// <summary>
        /// URL地址编码
        /// </summary>
        /// <param name="Input">输入字符串</param>
        /// <returns>返编码后的字符串</returns>
        public static string URLEncode(string Input)
        {
            if (string.IsNullOrEmpty(Input)) return string.Empty;
            else
                return HttpContext.Current.Server.UrlEncode(Input);
        }

        /// <summary>
        /// URL地址解码
        /// </summary>
        /// <param name="Input">输入字符串</param>
        /// <returns>返回解码后的字符串</returns>
        public static string URLDecode(string Input)
        {
            if (!string.IsNullOrEmpty(Input))
            {
                return HttpContext.Current.Server.UrlDecode(Input);
            }
            else
            {
                return string.Empty;
            }
        }

        /// <summary>
        /// 过滤特殊字符
        /// </summary>
        public static string Htmls(string Input)
        {
            if (!string.IsNullOrEmpty(Input))
            {
                string ihtml = Input.ToLower();
                ihtml = ihtml.Replace("<script", "&lt;script");
                ihtml = ihtml.Replace("script>", "script&gt;");
                ihtml = ihtml.Replace("</script", "&lt;/script");
                ihtml = ihtml.Replace("<%", "&lt;%");
                ihtml = ihtml.Replace("%>", "%&gt;");
                ihtml = ihtml.Replace("<$", "&lt;$");
                ihtml = ihtml.Replace("$>", "$&gt;");
                return ihtml;
            }
            else
            {
                return string.Empty;
            }
        }

        /// <summary>
        /// 字符串字符处理
        /// </summary>
        public static String ToTxt(String Input)
        {
            StringBuilder sb = new StringBuilder(Input);
            sb.Replace("&nbsp;", " ");
            sb.Replace("<br>", "\r\n");
            sb.Replace("<br>", "\n");
            sb.Replace("<br />", "\n");
            sb.Replace("<br />", "\r\n");
            sb.Replace("&lt;", "<");
            sb.Replace("&gt;", ">");
            sb.Replace("&amp;", "&");
            return sb.ToString();
        }

        /// <summary>
        /// 字符串字符处理
        /// </summary>
        public static String ToshowTxt(String Input)
        {
            StringBuilder sb = new StringBuilder(Input);
            sb.Replace("&lt;", "<");
            sb.Replace("&gt;", ">");
            sb.Replace("&quot;", "\"");
            return sb.ToString();
        }

        /// <summary>
        /// 把字符转化为文本格式
        /// </summary>
        /// <param name="Input"></param>
        /// <returns></returns>
        public static string ForTXT(string Input)
        {
            StringBuilder sb = new StringBuilder(Input);
            sb.Replace("<font", " ");
            sb.Replace("<span", " ");
            sb.Replace("<style", " ");
            sb.Replace("<div", " ");
            sb.Replace("<p", "");
            sb.Replace("</p>", "");
            sb.Replace("<label", " ");
            sb.Replace("&nbsp;", " ");
            sb.Replace("<br>", "");
            sb.Replace("<br />", "");
            sb.Replace("<br />", "");
            sb.Replace("&lt;", "");
            sb.Replace("&gt;", "");
            sb.Replace("&amp;", "");
            sb.Replace("<", "");
            sb.Replace(">", "");
            return sb.ToString();
        }

        /// <summary>
        /// 字符串字符处理
        /// </summary>
        public static String ToHtml(string Input)
        {
            if (!string.IsNullOrEmpty(Input))
            {
                StringBuilder sb = new StringBuilder(Input);
                sb.Replace("&", "&amp;");
                sb.Replace("<", "&lt;");
                sb.Replace(">", "&gt;");
                sb.Replace("\r\n", "<br />");
                sb.Replace("\n", "<br />");
                sb.Replace("\t", " ");
                return sb.ToString();
            }
            else
            {
                return string.Empty;
            }
        }

        #region 过滤Html

        /// <summary>
        /// 替换html中的特殊字符
        /// </summary>
        /// <param name="theString">需要进行替换的文本。</param>
        /// <returns>替换完的文本。</returns>
        public static string HtmlEncodeWithReplace(string theString)
        {
            theString = theString.Replace(">", "&gt;");
            theString = theString.Replace("<", "&lt;");
            theString = theString.Replace("  ", " &nbsp;");
            theString = theString.Replace("  ", " &nbsp;");
            theString = theString.Replace("\"", "&quot;");
            theString = theString.Replace("\'", "&#39;");
            theString = theString.Replace("\n", "<br/> ");
            return theString;
        }

        /// <summary>
        /// 过滤字符串中的html代码
        /// </summary>
        /// <param name="Str">传入字符串</param>
        /// <returns>过滤后的字符串</returns>
        public static string LostHTML(string Str)
        {
            string Re_Str = "";
            if (Str != null)
            {
                if (Str != string.Empty)
                {
                    string Pattern = "<\\/*[^<>]*>";
                    Re_Str = Regex.Replace(Str, Pattern, "");
                }
            }
            return (Re_Str.Replace("\\r\\n", "")).Replace("\\r", "");
        }

        /// <summary>
        /// 过滤HTML语法
        /// </summary>
        public static string FilterHTML(object input)
        {
            if (input == null)
            {
                return string.Empty;
            }
            else
            {
                string html = input.ToString();
                if (string.IsNullOrEmpty(html)) return string.Empty;
                System.Text.RegularExpressions.Regex regex1 = new System.Text.RegularExpressions.Regex(@"<[^>]*>", System.Text.RegularExpressions.RegexOptions.IgnoreCase);
                html = regex1.Replace(html, string.Empty);
                return html.Replace("\"", "“");
            }
        }

        public static string FilterLogHTML(string html)
        {
            if (string.IsNullOrEmpty(html)) return string.Empty;
            if (html.ToLower().IndexOf("<img") > -1 && html.ToLower().IndexOf(">") > -1)
            {
                html = "<span class=\"sp_reshow\">【图文日志】</span>" + html;
            }
            System.Text.RegularExpressions.Regex regex1 = new System.Text.RegularExpressions.Regex(@"<[^>]*>", System.Text.RegularExpressions.RegexOptions.IgnoreCase);
            html = regex1.Replace(html, string.Empty);
            return html;
        }

        /// <summary>
        /// 去掉HTML标签
        /// </summary>
        /// <param name="Htmlstring">带有HTML标签的字符串</param>
        /// <returns>string</returns>
        public static string NoHTML(string Htmlstring)
        {
            Htmlstring = Regex.Replace(Htmlstring, @"<script[^>]*?>.*?</script>", "", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"<(.[^>]*)>", "", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"([\r\n])[\s]+", "", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"-->", "", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"<!--.*", "", RegexOptions.IgnoreCase);

            Htmlstring = Regex.Replace(Htmlstring, @"&(quot|#34);", "\"", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"&(amp|#38);", "&", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"&(lt|#60);", "<", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"&(gt|#62);", ">", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"&(nbsp|#160);", " ", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"&(iexcl|#161);", "\xa1", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"&(cent|#162);", "\xa2", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"&(pound|#163);", "\xa3", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"&(copy|#169);", "\xa9", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"&#(\d+);", "", RegexOptions.IgnoreCase);

            Htmlstring.Replace("<", "");
            Htmlstring.Replace(">", "");
            Htmlstring.Replace("\r\n", "");

            return Htmlstring.Trim();
        }

        /// <summary>
        /// 过滤Script块
        /// </summary>
        /// <param name="sInput">Html源码</param>
        /// <returns></returns>
        public static string FilterScript(string sInput)
        {
            Regex regex = new Regex(@"<script[^>]*?>.*?</script>", RegexOptions.IgnoreCase);
            return regex.Replace(sInput, string.Empty);
        }

        /// <summary>
        /// 过滤链接
        /// </summary>
        /// <param name="sInput">Html源码</param>
        /// <returns></returns>
        public static string FilterLink(string sInput)
        {
            string strOutput = sInput;
            Regex rea = new Regex("<a[^>]*href=(\"\"(?<href>[^\"\"]*)\"\"|'(?<href>[^']*)'|(?<href>[^\\s>]*))[^>]*>(?<text>.*?)</a>", RegexOptions.None);
            MatchCollection mc = rea.Matches(strOutput);
            foreach (Match m in mc)
            {
                strOutput = Regex.Replace(
                    strOutput,
                    m.Groups["text"].Value,
                    Regex.Replace(m.Groups["text"].Value, "<[^>]*>", "")
                    );
            }

            return strOutput;
        }

        /// <summary>
        /// 去除script
        /// </summary>
        public static string loseScript(string html)
        {
            if (string.IsNullOrEmpty(html)) return string.Empty;
            System.Text.RegularExpressions.Regex regex1 = new System.Text.RegularExpressions.Regex(@"<script[\s\S]+</script *>", System.Text.RegularExpressions.RegexOptions.IgnoreCase);
            html = regex1.Replace(html, ""); //过滤<script></script>标记
            return html;
        }

        /// <summary>
        /// 去除iframe
        /// </summary>
        /// <param name="html"></param>
        /// <returns></returns>
        public static string loseIframe(string html)
        {
            if (string.IsNullOrEmpty(html)) return string.Empty;
            System.Text.RegularExpressions.Regex regex1 = new System.Text.RegularExpressions.Regex(@"<iframe[\s\S]+</iframe *>", System.Text.RegularExpressions.RegexOptions.IgnoreCase);
            System.Text.RegularExpressions.Regex regex2 = new System.Text.RegularExpressions.Regex(@"<frameset[\s\S]+</frameset *>", System.Text.RegularExpressions.RegexOptions.IgnoreCase);
            html = regex1.Replace(html, ""); //过滤<script></script>标记
            html = regex2.Replace(html, ""); //过滤href=javascript: (<A>) 属性
            return html;
        }

        /// <summary>
        /// 去除除IMG以外的HTML
        /// </summary>
        /// <param name="html"></param>
        /// <returns></returns>
        public static string loseExceptImg(string html)
        {
            if (string.IsNullOrEmpty(html)) return string.Empty;
            System.Text.RegularExpressions.Regex regex = new System.Text.RegularExpressions.Regex(@"<(?!/?img)[\s\S]*?>", System.Text.RegularExpressions.RegexOptions.IgnoreCase);
            html = regex.Replace(html, "");
            return html;
        }

        /// <summary>
        /// Strips HTML comments from the specified text
        /// </summary>
        /// <param name="text">The text</param>
        /// <returns>The text without comments</returns>
        public static string RemoveHtmlComments(string text)
        {
            if (!String.IsNullOrEmpty(text))
            {
                Regex commentStripper = new Regex("(?:&lt;!--)(?:(\\w|[ ]|\\W)*)(?:--&gt;)|(?:<!--)(?:(\\w|[ ]|\\W)*)(?:-->)");
                return commentStripper.Replace(text, string.Empty);
            }
            return text;
        }

        /// <summary>
        /// 过滤html标签
        /// </summary>
        /// <param name="strHtml">html的内容</param>
        /// <returns></returns>
        public static string HTML2String(string strHtml)
        {
            string[] aryReg ={
								  @"<script[^>]*?>.*?</script>",

								  @"<(\/\s*)?!?((\w+:)?\w+)(\w+(\s*=?\s*(([""'])(\\[""'tbnr]|[^\7])*?\7|\w+)|.{0})|\s)*?(\/\s*)?>",
								  @"([\r\n])[\s]+",
								  @"&(quot|#34);",
								  @"&(amp|#38);",
								  @"&(lt|#60);",
								  @"&(gt|#62);", 
								  @"&(nbsp|#160);", 
								  @"&(iexcl|#161);",
								  @"&(cent|#162);",
								  @"&(pound|#163);",
								  @"&(copy|#169);",
								  @"&#(\d+);",
								  @"-->",
								  @"<!--.*\n"
							  };

            string[] aryRep = {
								   "",
								   "",
								   "",
								   "\"",
								   "&",
								   "<",
								   ">",
								   " ",
								   "\xa1",//chr(161),
								   "\xa2",//chr(162),
								   "\xa3",//chr(163),
								   "\xa9",//chr(169),
								   "",
								   "\r\n",
								   ""
							   };

            string newReg = aryReg[0];
            string strOutput = strHtml;
            for (int i = 0; i < aryReg.Length; i++)
            {
                System.Text.RegularExpressions.Regex regex = new System.Text.RegularExpressions.Regex(aryReg[i], System.Text.RegularExpressions.RegexOptions.IgnoreCase);
                strOutput = regex.Replace(strOutput, aryRep[i]);
            }
            strOutput.Replace("<", "");
            strOutput.Replace(">", "");
            strOutput.Replace("\r\n", "");
            return strOutput;
        }

        #endregion

        /// <summary>
        /// 把图文分解成图，文
        /// </summary>
        /// <param name="html">输入HTML</param>
        /// <param name="img">图</param>
        /// <param name="text">文</param>
        public static void splitImgAndText(string html, out string img, out string text)
        {
            if (html == null)
            {
                img = "";
                text = "";
                return;
            }
            Regex regex = new System.Text.RegularExpressions.Regex(@"<img[\s\S]+</img *>|<img[^>]+/? *>", System.Text.RegularExpressions.RegexOptions.IgnoreCase);
            Match m = regex.Match(html);
            string imgstr = string.Empty;
            while (m.Success)
            {
                imgstr += m.Value;
                m = m.NextMatch();
            }
            string textStr = FilterHTML(html);
            img = imgstr;
            text = textStr;
        }

        /// <summary>
        /// Appends a CSS class to a control.
        /// </summary>
        /// <param name="control">The control.</param>
        /// <param name="newClass">The new class.</param>
        public static void AppendCssClass(WebControl control, string newClass)
        {
            if (control == null)
                throw new ArgumentNullException("Cannot add a css class to a null control");

            if (newClass == null)
                throw new ArgumentNullException("Cannot add a null css class to a control");

            string existingClasses = control.CssClass;
            if (String.IsNullOrEmpty(existingClasses))
            {
                control.CssClass = newClass;
                return;
            }

            string[] classes = existingClasses.Split(' ');
            foreach (string attributeValue in classes)
            {
                if (String.Equals(attributeValue, newClass, StringComparison.Ordinal))
                {
                    //value's already in there.
                    return;
                }
            }
            control.CssClass += " " + newClass;
        }

        /// <summary>
        /// Removes a CSS class to a control.
        /// </summary>
        /// <param name="control">The control.</param>
        /// <param name="classToRemove">The new class.</param>
        public static void RemoveCssClass(WebControl control, string classToRemove)
        {
            if (control == null)
                throw new ArgumentNullException("Cannot remove a css class from a null control");

            if (classToRemove == null)
                throw new ArgumentNullException("Cannot remove a null css class from a control");

            string existingClasses = control.CssClass;
            if (String.IsNullOrEmpty(existingClasses))
                return; //nothing to remove

            string[] classes = existingClasses.Split(new string[] { " ", "\t", "\r\n", "\n", "\r" }, StringSplitOptions.RemoveEmptyEntries);
            string newClasses = string.Empty;
            foreach (string cssClass in classes)
            {
                if (!String.Equals(cssClass, classToRemove, StringComparison.Ordinal))
                {
                    newClasses += cssClass + " ";
                }
            }

            if (newClasses.EndsWith(" "))
                newClasses = newClasses.Substring(0, newClasses.Length - 1);
            control.CssClass = newClasses;
        }

        /// <summary>
        /// Appends the attribute value to the control appropriately.
        /// </summary>
        /// <param name="name"></param>
        /// <param name="value"></param>
        public static void AppendAttributeValue(WebControl control, string name, string value)
        {
            string existingValue = control.Attributes[name];
            if (String.IsNullOrEmpty(existingValue))
            {
                control.Attributes[name] = value;
                return;
            }
            else
            {
                string[] attributeValues = control.Attributes[name].Split(' ');
                foreach (string attributeValue in attributeValues)
                {
                    if (String.Equals(attributeValue, value, StringComparison.Ordinal))
                    {
                        //value's already in there.
                        return;
                    }
                }
                control.Attributes[name] += " " + value;
            }
        }

        /// <summary>
        /// Converts the entry body into XHTML compliant text. 
        /// Returns false if it encounters a problem in doing so.
        /// </summary>
        /// <param name="entry">Entry.</param>
        /// <returns></returns>
        //public static bool ConvertHtmlToXHtml(Entry entry)
        //{
        //    SgmlReader reader = new SgmlReader();
        //    reader.SetBaseUri(Config.CurrentBlog.RootUrl.ToString());
        //    reader.DocType = "html";
        //    reader.WhitespaceHandling = WhitespaceHandling.All;
        //    reader.InputStream = new StringReader("<html>" + entry.Body + "</html>");
        //    reader.CaseFolding = CaseFolding.ToLower;
        //    StringWriter writer = new StringWriter();
        //    XmlTextWriter xmlWriter = null;
        //    try
        //    {
        //        xmlWriter = new XmlTextWriter(writer);

        //        while (reader.Read())
        //        {
        //            xmlWriter.WriteNode(reader, true);
        //        }
        //    }
        //    finally
        //    {
        //        if (xmlWriter != null)
        //        {
        //            xmlWriter.Close();
        //        }
        //    }

        //    string xml = writer.ToString();
        //    entry.Body = xml.Substring("<html>".Length, xml.Length - "<html></html>".Length);
        //    return true;
        //}

        /// <summary>
        /// Tests the specified string looking for illegal characters 
        /// or html tags.
        /// </summary>
        /// <param name="s">S.</param>
        /// <returns></returns>
        public static bool HasIllegalContent(string s)
        {
            if (s == null || s.Trim().Length == 0)
            {
                return false;
            }
            if (s.IndexOf("<script") > -1
                || s.IndexOf("&#60script") > -1
                || s.IndexOf("&60script") > -1
                || s.IndexOf("%60script") > -1)
            {
                throw new Exception("Illegal Characters Found");
            }
            return false;
        }

        /// <summary>
        /// Wraps an anchor tag around urls.
        /// </summary>
        /// <param name="text">Text.</param>
        /// <returns></returns>
        public static string EnableUrls(string text)
        {
            string pattern = @"(http|ftp|https):\/\/[\w]+(.[\w]+)([\w\-\.,@?^=%&amp;:/~\+#]*[\w\-\@?^=%&amp;/~\+#])";
            MatchCollection matches = Regex.Matches(text, pattern, RegexOptions.IgnoreCase | RegexOptions.Compiled);
            foreach (Match m in matches)
            {
                text = text.Replace(m.ToString(), "<a rel=\"nofollow external\" href=\"" + m.ToString() + "\">" + m.ToString() + "</a>");
            }
            return text;
        }


        /// <summary>
        /// The only HTML we will allow is hyperlinks. 
        /// We will however, check for line breaks and replace 
        /// them with <br />
        /// </summary>
        /// <param name="stringToTransform"></param>
        /// <returns></returns>
        public static string SafeFormat(string stringToTransform)
        {
            if (stringToTransform == null)
                throw new ArgumentNullException("stringToTransform", "Cannot transform a null string.");

            stringToTransform = HttpContext.Current.Server.HtmlEncode(stringToTransform);
            string brTag = "<br />";
            return stringToTransform.Replace(Environment.NewLine, brTag);
        }

        /// <summary>
        /// Strips the RTB, whatever that is.
        /// </summary>
        /// <param name="text">Text.</param>
        /// <param name="host">Host.</param>
        /// <returns></returns>
        public static string StripRTB(string text, string host)
        {
            string s = Regex.Replace(text, "/localhost/S*Admin/", "", RegexOptions.IgnoreCase);
            return Regex.Replace(s, "<A href=\"/", "<A href=\"" + "http://" + host + "/", RegexOptions.IgnoreCase);
        }

        /// <summary>
        /// Checks the text and prepends "http://" if it doesn't have it already.
        /// </summary>
        /// <param name="text">Text.</param>
        /// <returns></returns>
        public static Uri CheckForUrl(string text)
        {
            if (text == null)
                return null;

            text = text.Trim();

            if (String.IsNullOrEmpty(text))
                return null;

            if (!text.StartsWith("http://", StringComparison.InvariantCultureIgnoreCase))
            {
                text = "http://" + text;
            }

            return new Uri(text);
        }

        private static string HtmlSafe(string text)
        {
            //replace &, <, >, and line breaks with <br />
            text = text.Replace("&", "&amp;");
            text = text.Replace("<", "&lt;");
            text = text.Replace(">", "&gt;");
            text = text.Replace("\r", string.Empty);
            text = text.Replace("\n", "<br />");
            return text;
        }

        /// <summary>
        /// Removes any non-permitted attributes for the given tagName. The permitted attributes 
        /// are determined by the given allowedHtml collection.
        /// </summary>
        /// <param name="tagName"></param>
        /// <param name="match"></param>
        /// <param name="allowedHtml"></param>
        /// <returns></returns>
        /// <remarks>This will be a high volume method, so make it as efficient as possible</remarks>
        private static string FilterAttributes(string tagName, Match match, NameValueCollection allowedHtml)
        {
            string allowedAttributesText = allowedHtml[tagName];

            if (allowedAttributesText != null && allowedAttributesText.Length > 0)
            {
                StringBuilder attrSB = new StringBuilder();

                //look to see which tag's attributes we are matching
                char[] splitter = { ',' };

                NameValueCollection attributes = GetAttributeNameValues(match);

                string[] allowedAttrs = allowedHtml[tagName].ToLower(CultureInfo.InvariantCulture).Split(splitter);

                // go thru each matched attribute, and determine if it's allowed
                foreach (string attributeName in attributes.Keys)
                {
                    foreach (string allowedAttr in allowedAttrs)
                    {
                        if (String.Equals(allowedAttr.Trim(), attributeName, StringComparison.InvariantCultureIgnoreCase))
                        {
                            // found an allowed attribute, so get the attribute value
                            string attrValue = attributes[attributeName];

                            // and now add the full attribute (key=value) to be returned
                            attrSB.Append(" " + attributeName.ToLower(CultureInfo.InvariantCulture) + "=\"" + attrValue + "\"");
                        }
                    }
                }
                return attrSB.ToString();
            }
            return string.Empty;
        }

        private static NameValueCollection GetAttributeNameValues(Match match)
        {
            CaptureCollection nameCaptures = match.Groups["attName"].Captures;
            CaptureCollection valueCaptures = match.Groups["attVal"].Captures;

            NameValueCollection attributes = new NameValueCollection();

            if (nameCaptures.Count == valueCaptures.Count)
            {
                for (int i = 0; i < nameCaptures.Count; i++)
                {
                    attributes.Add(nameCaptures[i].Value, valueCaptures[i].Value);
                }
                return attributes;
            }

            if (valueCaptures.Count == 0)
            {
                return attributes;
            }

            //this is a much more complicated issue.  
            //One of the attribute names doesn't have a value.
            //so we need to match them up somehow.
            int valueIndex = 0;
            for (int i = 0; i < nameCaptures.Count; i++)
            {
                Capture currentNameCapture = nameCaptures[i];
                Capture currentValueCapture;
                string name = currentNameCapture.Value;

                if (valueIndex == valueCaptures.Count)
                {
                    //No more values to worry about.
                    continue;
                }

                currentValueCapture = valueCaptures[valueIndex];

                //Peek ahead.
                if (i < nameCaptures.Count - 1)
                {
                    Capture peekAhead = nameCaptures[i + 1];
                    if (peekAhead.Index > currentValueCapture.Index && currentValueCapture.Index > currentNameCapture.Index)
                    {
                        attributes.Add(name, currentValueCapture.Value);
                        //We are on the right value.
                        valueIndex++;
                        continue;
                    }
                }
                else
                {
                    //we're on the last item.
                    if (currentValueCapture.Index > currentNameCapture.Index)
                    {
                        attributes.Add(name, currentValueCapture.Value);
                        //We are on the right value.
                        valueIndex++;
                        continue;
                    }
                }
            }
            return attributes;
        }

        /// <summary>
        /// Returns a string collection of URLs within the specified text.
        /// </summary>
        /// <param name="text">The text.</param>
        /// <returns></returns>
        public static StringCollection GetLinks(string text)
        {
            StringCollection links = new StringCollection();
            string sPattern = @"(?:[hH][rR][eE][fF]\s*=)" +
                @"(?:[\s""']*)(?!#|[Mm]ailto|[lL]ocation.|[jJ]avascript|.*css|.*this\.)" +
                @"(.*?)(?:[\s>""'])";

            Regex r = new Regex(sPattern, RegexOptions.IgnoreCase);
            Match m;
            string link;
            for (m = r.Match(text); m.Success; m = m.NextMatch())
            {
                if (m.Groups.ToString().Length > 0)
                {
                    link = m.Groups[1].ToString();
                    if (!links.Contains(link))
                    {
                        links.Add(link);
                    }
                }
            }
            return links;
        }

        /// <summary>
        /// Parses the URI.
        /// </summary>
        /// <param name="uri">The URI.</param>
        /// <returns></returns>
        public static Uri ParseUri(string uri)
        {
            if (uri == null)
                return null;

            try
            {
                return new Uri(uri);
            }
            catch (UriFormatException)
            {
                return null;
            }
        }

        #region 将Html中的图片转化Base64编码

        public static string ConvertImage2Base64(string html)
        {
            string pattern = @"src=""(?<FirstGroup>[^""]+)""";
            MatchCollection mc = Regex.Matches(html, pattern, RegexOptions.IgnoreCase | RegexOptions.Compiled);

            if (mc.Count == 0)
            {
                return string.Empty;
            }
            foreach (Match match in mc)
            {
                if (match.Success)
                {
                    GroupCollection gc = match.Groups;
                    if (gc == null || gc["FirstGroup"] == null)
                    {
                        continue;
                    }
                    string filePath = gc["FirstGroup"].Value;
                    string base64 = GetBase64File(filePath.Substring(8));

                    html = html.Replace(filePath, string.Format("data:image/jpeg;base64,{0}", base64));
                }
            }

            return html;
        }        
        /// <summary>
        /// 将本地图片转为base64编码
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        private static string GetBase64File(string path)
        {
            string result = string.Empty;
            using (System.IO.FileStream fs = new System.IO.FileStream(path, System.IO.FileMode.Open))
            {
                byte[] bytes = new byte[fs.Length];
                fs.Read(bytes, 0, Convert.ToInt32(fs.Length));
                result = Convert.ToBase64String(bytes);
            }
            return result;
        }

        #endregion

    }
}
